﻿#include "zz.h"

#if defined(__QG_H__)

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

using namespace tpl;

//
extern "C" KAPI qgTexture* qg_cube_map(qgDevice* pdev, const kwchar* filename);

//
qgMayaCamera* gcam;
qgLayout* glo;
Vec2 grot(0.0f, 0.0f);
float gscl = 1.0f;

bool _mouse_move(qgSevMouseMove& e)
{
	static Point pt(0, 0);

	Point dt(pt.x - e.x, pt.y - e.y);
	pt.Set(e.x, e.y);

	if (gcam && e.state == QIMM_RIGHT)
		gcam->RefreshAngle(Vec3((float)dt.y, (float)dt.x, 0.0f), 0.005f);
	else if (e.state == QIMM_LEFT)
	{
		grot.x += dt.y * 0.01f;
		grot.y += dt.x * -0.01f;
	}

	return true;
}

int main(void)
{
	k_mesg("MAYA CAMERA\n");

	qgDevice* dev = qgDevice::New("dx9", 640, 480, QGSDF_LAYOUT | QGSDF_AUTO /*| QGSDF_INFO*/);

	if (dev)
	{
#if _SB_DEBUG_
		dev->Mount(QG_WORK_PATH);
#else
		//dev->Mount(QG_WORK_PATH);
		dev->Mount();
#endif

		qgStub* stub = dev->GetStub();
		stub->AddMouseMoveHandler(qgSevMouseMoveFunc(&_mouse_move));

		//
		qgFreeType* font = qgFreeType::New();

		//
		static qgLayoutElement s_le[] =
		{
			{QGDLOU_POSITION, 0, QGDLOT_FLOAT3, 0, 0, },
			//{QGDLOU_COLOR, 0, QGDLOT_FLOAT4, 0, 0, },
			{QGDLOU_TEXTURE, 0, QGDLOT_FLOAT2, 0, 0, },
			{QGDLOU_NORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_TANGENT, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_BINORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
		};
		glo = dev->CreateLayout(s_le);

		qgShader* shddp = dev->CreateShader(NULL);
		shddp->BindFile(QGSHADER_PS, "imt9.hlsl", 0);
		shddp->BindFile(QGSHADER_VS, "imt9.hlsl", 0);
		shddp->Link();

		qgShader* shdsd = dev->CreateShader(NULL);
		shdsd->BindFile(QGSHADER_PS, "imz9.hlsl", 0);
		shdsd->BindFile(QGSHADER_VS, "imz9.hlsl", 0);
		shdsd->Link();

		qgSplr* splrlin = dev->CreateSplr(qgSplrDataEx(QGFLT_MAG_MIN_MIP_LINEAR));
		qgSplr* splrpnt = dev->CreateSplr(qgSplrDataEx(QGFLT_MAG_MIN_MIP_POINT));

		//
		gcam = qgMayaCamera::New();
		gcam->SetProcessLayout(true);
		gcam->SetMoveSpeed(50.0f);
		gcam->SetFar(200.0f);
		gcam->SetViewPos(Vec3(0.0f, 227.0f, 622.0f));

		//
		qgTexture* cube = qg_cube_map(dev, L"d:\\LobbyCube.dds");

		//
		qgTexture* m1norm = dev->CreateTexture("IronManMap01Norm.png", 0);
		qgTexture* m1spec = dev->CreateTexture("IronManMap01Spec.png", 0);
		qgTexture* m2norm = dev->CreateTexture("IronManMap02Norm.png", 0);
		qgTexture* m2spec = dev->CreateTexture("IronManMap02Spec.png", 0);

		qgSmm* smm = qgSmm::New(0, "irm.smm", 0);
		qgSmm* smd = qgSmm::New(0, "imn.smm", 0);
		kint nmsh = smm->GetMeshCount();

		for (kint i = 0; i < nmsh; i++)
		{
			qgSmmMesh* m = smm->GetMeshNth(i);
			qgTexture* t = m->GetTexture(0);
			if (!t)
				continue;

			const char* k = t->GetKey();
			if (k_strnicmp(k, "IronManMap01", 12) == 0)
			{
				m->SetTexture(1, m1spec);
				m->SetTexture(2, m1norm);
			}
			else if (k_strnicmp(k, "IronManMap02", 12) == 0)
			{
				m->SetTexture(1, m2spec);
				m->SetTexture(2, m2norm);
			}
		}

		m1norm->Unload();
		m1spec->Unload();
		m2norm->Unload();
		m2spec->Unload();

		//
		while (dev->Run())
		{
			float adv = stub->GetAdvance();

			qgUimKey k;
			stub->GetKeyTable(&k);

			if (k.key[QIK_Q]) grot.y -= KM_PI_HALF * adv;
			if (k.key[QIK_W]) grot.y += KM_PI_HALF * adv;
			if (k.key[QIK_A]) grot.x -= KM_PI_HALF * adv;
			if (k.key[QIK_S]) grot.x += KM_PI_HALF * adv;
			if (k.key[QIK_1]) gscl -= 5.0f * adv;
			if (k.key[QIK_2]) gscl += 5.0f * adv;

#if 1
			bool ismove = false;
			if (k.key[QIK_I]) ismove = true, gcam->MoveKey(QSFPSWMV_BACKWARD);
			if (k.key[QIK_K]) ismove = true, gcam->MoveKey(QSFPSWMV_FORWARD);
			if (k.key[QIK_J]) ismove = true, gcam->MoveKey(QSFPSWMV_RIGHT);
			if (k.key[QIK_L]) ismove = true, gcam->MoveKey(QSFPSWMV_LEFT);
			if (k.key[QIK_U]) ismove = true, gcam->MoveKey(QSFPSWMV_UP);
			if (k.key[QIK_O]) ismove = true, gcam->MoveKey(QSFPSWMV_DOWN);

			if (ismove)
				gcam->RefreshMove(adv);
#endif
			gcam->Update(adv);

			//
			if (dev->Enter())
			{
				dev->SetTM(QGTMS_PROJ, gcam->GetProjTM());
				dev->SetTM(QGTMS_VIEW, gcam->GetViewTM());

				dev->SetPropVec(0, Vec4(0.0f, 500.0f, 500.0f, 1.0f));
				dev->SetPropVec(1, Vec4(1.0f, 1.0f, 1.0f, 1.0f));
				dev->SetPropVec(2, Vec4(*(Vec3*)&gcam->GetViewTM()._41, 1.0f));

				//
				smm->SetLocation(Vec3(0.0f, 0.0f, 0.0f));
				smm->SetRotation(Quat::Rotation(Vec3(grot.x, grot.y + KM_PI, 0.0f)));
				smm->SetScaling(Vec3(gscl, gscl, gscl));
				smm->Update(adv);
				dev->SetShader(shddp);
				dev->SetLayout(glo);
				dev->SetSplr(0, splrlin);
				dev->SetSplr(1, splrpnt);
				dev->SetSplr(2, splrpnt);
				dev->SetSplr(3, splrlin);
				dev->SetTexture(3, cube);
				smm->Draw();

				//
				Mat4 tm = smm->GetCalcTM();
				smd->SetLocalTM(tm * Mat4::Shadow(Vec4(Vec3(0.2f, -1.0f, -0.9f).Normalize(), 0.0f), Plane(0.0f, -1.0f, 0.0f, 0.0f)));
				smd->Update(adv);
				//smd->UpdateFrame(adv);
				//smd->UpdateSub(adv);
				dev->SetShader(shdsd);
				dev->SetLayout(glo);
				dev->SetTexture(0, NULL);
				dev->SetTexture(1, NULL);
				dev->SetTexture(2, NULL);
				dev->SetTexture(3, NULL);
				smd->DrawOnly();

				//
				qgUimMouse m;
				stub->GetMouse(&m);
				Vec3 v = gcam->GetViewPos();

				font->WriteFormat(5, 5, 0, "[%.2f] [%d:%d] [%.2f, %.2f, %.2f]", stub->GetRunFps(),
					m.point.x, m.point.y, v.x, v.y, v.z);

				dev->Leave();
				dev->Flush();
			}
		}

		cube->Unload();
		smd->Unload();
		smm->Unload();

		font->Unload();
		dev->Unload();
	}

	return 0;
}

#endif
